﻿using System;
using System.Collections.Generic;

namespace System.Diagnostics.Contracts
{
#if NET35
	class Contract
	{
		[Conditional("CONTRACTS_FULL")]
		[Conditional("DEBUG")]
		public static void Assert(bool condition) { Debug.Assert(condition); }
		[Conditional("DEBUG")]
		[Conditional("CONTRACTS_FULL")]
		public static void Assert(bool condition, string userMessage) { Debug.Assert(condition, userMessage); }
		[Conditional("DEBUG")]
		[Conditional("CONTRACTS_FULL")]
		public static void Assume(bool condition) { Debug.Assert(condition); }
		[Conditional("DEBUG")]
		[Conditional("CONTRACTS_FULL")]
		public static void Assume(bool condition, string userMessage) { Debug.Assert(condition, userMessage); }
		[Conditional("CONTRACTS_FULL")]
		public static void EndContractBlock() { }
		[Conditional("CONTRACTS_FULL")]
		public static void Ensures(bool condition) { Debug.Assert(condition); }
		[Conditional("CONTRACTS_FULL")]
		public static void Ensures(bool condition, string userMessage) { Debug.Assert(condition, userMessage); }
		[Conditional("CONTRACTS_FULL")]
		public static void EnsuresOnThrow<TException>(bool condition) where TException : Exception
		{
			if (!condition)
				throw (Exception)Activator.CreateInstance<TException>();
		}
		[Conditional("CONTRACTS_FULL")]
		public static void EnsuresOnThrow<TException>(bool condition, string userMessage) where TException : Exception
		{
			if (!condition)
				throw (Exception)Activator.CreateInstance(typeof(TException), new object[] { userMessage });
		}
		public static bool Exists<T>(IEnumerable<T> collection, Predicate<T> predicate)
		{
			if (collection == null)
				throw new ArgumentNullException("collection");
			if (predicate == null)
				throw new ArgumentNullException("predicate");

			foreach (var item in collection)
				if (predicate(item)) return true;

			return false;
		}
		public static bool Exists(int fromInclusive, int toExclusive, Predicate<int> predicate)
		{
			if (predicate == null)
				throw new ArgumentNullException("predicate");

			for (int i = fromInclusive; i < toExclusive; i++)
			{
				if (predicate(i))
					return true;
			}
			return false;
		}
		public static bool ForAll<T>(IEnumerable<T> collection, Predicate<T> predicate)
		{
			var result = true;
			foreach (var item in collection)
				result = result && predicate(item);

			return result;
		}
		public static bool ForAll(int fromInclusive, int toExclusive, Predicate<int> predicate)
		{
			var result = true;
			for (var i = fromInclusive; i < toExclusive; i++)
				result = result && predicate(i);

			return result;
		}
		[Conditional("CONTRACTS_FULL")]
		public static void Invariant(bool condition) { Debug.Assert(condition); }
		[Conditional("CONTRACTS_FULL")]
		public static void Invariant(bool condition, string userMessage) { Debug.Assert(condition, userMessage); }
		public static T OldValue<T>(T value)
		{
			return default(T);
		}
		public static void Requires<TException>(bool condition) where TException : Exception
		{
			if (!condition)
				throw (Exception)Activator.CreateInstance<TException>();
		}
		[Conditional("CONTRACTS_FULL")]
		public static void Requires(bool condition)
		{
			if (!condition)
				throw new ArgumentException("Requirement failed");
		}
		[Conditional("CONTRACTS_FULL")]
		public static void Requires(bool condition, string userMessage)
		{
			if (!condition)
				throw new ArgumentException(userMessage);
		}
		public static void Requires<TException>(bool condition, string userMessage) where TException : Exception
		{
			if (!condition)
				throw (Exception)Activator.CreateInstance(typeof(TException), new object[] { userMessage });
		}
		public static T Result<T>() { return default(T); }
		public static T ValueAtReturn<T>(out T value) { value = default(T); return value; }
	} 
#endif
}
